use crate::config::app_error::AppResult;
use crate::extension::index::index::index_specs::IndexSpecs;
use crate::extension::index::index::query::index_attribute::{
    multi_value_attribute, simple_attribute,
};
use crate::extension::index::index::query::index_spec::IndexSpec;
use crate::extension::index::scheme_manager::SchemeManager;
use crate::extension::model::role::Role;
use crate::extension::model::role_binding::RoleBinding;
use crate::extension::model::user::User;
use crate::extension::model::user;
use halo_model::ExtensionOperator;
use std::collections::HashSet;

pub async fn init() -> AppResult<()> {
    let mut scheme_manager = SchemeManager::new();
    scheme_manager
        .register_fun::<_, User>(|spec| {
            spec.add(IndexSpec::new_type(
                "spec.displayName",
                simple_attribute(User::KIND, |user: &User| user.spec.display_name.clone()),
            ))?;

            spec.add(IndexSpec::new_type(
                "spec.email",
                simple_attribute(User::KIND, |user: &User| user.spec.email.clone()),
            ))?;

            spec.add(IndexSpec::new_type(
                user::USER_RELATED_ROLES_INDEX,
                multi_value_attribute(User::KIND, |user: &User| {
                    if let Some(annotations) = user.get_metadata().get_annotations() {
                        if let Some(role_names) =
                            annotations.get(&user::ROLE_NAMES_ANNO.to_string())
                        {
                            return serde_json::from_str(role_names).unwrap_or(HashSet::new());
                        }
                    }
                    return HashSet::new();
                }),
            ))?;
            Ok(())
        })
        .await;
    scheme_manager
        .register::<Role>()
        .await;
    scheme_manager
        .register::<RoleBinding>()
        .await;

    Ok(())
}
